package cn.bnjy.util;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Map;

/**
 * 描述：请求工具类
 *
 * @date: 2018/11/3 14:29
 * @author: chavin
 */
@Slf4j
public class HttpUtils {

    private static final int CONNECT_TIMEOUT = 5000;        // 超时时间
    private static final int REQUEST_TIMEOUT = 5000;        // 请求超时时间
    private static final int SOCKET_TIMEOUT = 5000;         // socket通信时间

    private static CloseableHttpClient httpClient;

    /**
     * 初始化
     */
    static {
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        cm.setMaxTotal(100);
        cm.setDefaultMaxPerRoute(20);
        cm.setDefaultMaxPerRoute(50);
        httpClient = HttpClients.custom().setConnectionManager(cm).build();
    }

    /**
     * get请求
     * @param url
     * @return
     */
    public static String get(String url) {
        log.info("执行get请求，url: {}, param: {}", url, null);
        LocalDateTime startTime = LocalDateTime.now();
        CloseableHttpResponse response = null;
        BufferedReader in = null;
        String result = "";
        try {
            HttpGet httpGet = new HttpGet(url);
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setConnectionRequestTimeout(REQUEST_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
            httpGet.setConfig(requestConfig);
            httpGet.setConfig(requestConfig);
            httpGet.addHeader("Content-type", "application/json; charset=utf-8");
            httpGet.setHeader("Accept", "application/json");
            response = httpClient.execute(httpGet);
            in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            StringBuffer sb = new StringBuffer();
            String line;
            String NL = System.getProperty("line.separator");
            while ((line = in.readLine()) != null) {
                sb.append(line + NL);
            }
            in.close();
            result = sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != response) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        LocalDateTime endTime = LocalDateTime.now();
        long time = ChronoUnit.MILLIS.between(startTime, endTime);
        log.info("执行get请求完毕，耗时：{}ms，返回结果：{}", time, result);
        return result;
    }

    /**
     * post请求
     * @param url
     * @param params
     * @return
     */
    public static String post(String url, Map<String, Object> params) {
        String json = JSON.toJSONString(params);
        return post(url, json);
    }

    /**
     * post请求
     * @param url
     * @param params
     * @return
     */
    public static String post(String url, String params) {
        log.info("执行post请求，url: {}, param: {}", url, params);
        LocalDateTime startTime = LocalDateTime.now();
        CloseableHttpResponse response = null;
        BufferedReader in = null;
        String result = "";
        try {
            HttpPost httpPost = new HttpPost(url);
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setConnectionRequestTimeout(REQUEST_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
            httpPost.setConfig(requestConfig);
            httpPost.setConfig(requestConfig);
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");
            httpPost.setHeader("Accept", "application/json");
            httpPost.setEntity(new StringEntity(params, Charset.forName("UTF-8")));
            response = httpClient.execute(httpPost);
            in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            StringBuffer sb = new StringBuffer();
            String line;
            String NL = System.getProperty("line.separator");
            while ((line = in.readLine()) != null) {
                sb.append(line + NL);
            }
            in.close();
            result = sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != response) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        LocalDateTime endTime = LocalDateTime.now();
        long time = ChronoUnit.MILLIS.between(startTime, endTime);
        log.info("执行post请求完毕，耗时：{}ms，返回结果：{}", time, result);
        return result;
    }


    /**
     * 将网络图片保存到本地
     * @param picUrl    网络图片地址
     * @param fileName  要保存的文件名
     * @param filePath      要保存的图片路径
     * @return
     */
    public static String savePicFromUrl(String picUrl, String fileName, String filePath) {
        log.info("执行保存网络图片到本地请求，picUrl: {}, fileName: {}, filePath: {}", picUrl, fileName, filePath);
        LocalDateTime startTime = LocalDateTime.now();
        HttpURLConnection httpUrl = null;
        URL url = null;
        byte[] buf = new byte[1024];
        int size = 0;
        FileOutputStream fileOutputStream = null;
        BufferedInputStream bufferedInputStream = null;
        String file = null;
        try {
            if(StringUtils.isBlank(picUrl)) {
                return null;
            }
            if(StringUtils.isBlank(fileName)) {
                fileName = String.valueOf(System.currentTimeMillis());
                if(fileName.indexOf(".") == -1) {
                    fileName += ".jpg";
                }
            }
            if(StringUtils.isBlank(filePath)) {
                filePath = CommonUtils.isWindows() ? "D://wx/static/images/qrcode" : "/home/wx/static/images/qrcode";
                File pfile = new File(filePath);
                if(!pfile.exists()) {
                    pfile.mkdirs();
                }
            }
            file = filePath + File.separator + fileName;
            url = new URL(picUrl);
            httpUrl = (HttpURLConnection)url.openConnection();
            httpUrl.connect();
            bufferedInputStream = new BufferedInputStream(httpUrl.getInputStream());
            fileOutputStream = new FileOutputStream(file);
            while ((size = bufferedInputStream.read(buf)) != -1) {
                fileOutputStream.write(buf, 0, size);
            }
            fileOutputStream.flush();
        } catch (Exception e) {
            log.error("保存图片异常：", e);
        } finally {
            try {
                if(fileOutputStream != null) {
                    fileOutputStream.close();
                }
                if(bufferedInputStream != null) {
                    bufferedInputStream.close();
                }
                if(httpUrl != null) {
                    httpUrl.disconnect();
                }
            } catch (IOException e) {
                log.error("关闭流异常：", e);
            }
        }
        LocalDateTime endTime = LocalDateTime.now();
        long time = ChronoUnit.MILLIS.between(startTime, endTime);
        log.info("执行post请求完毕，耗时：{}ms，文件保存地址：{}", time, file);
        return file;
    }

}
